package lew.bing.tom;

import groovy.lang.Script;
import groovy.util.GroovyScriptEngine;
import lombok.extern.slf4j.Slf4j;

import javax.servlet.ServletContext;
import java.io.File;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.Stack;
import java.util.concurrent.ConcurrentHashMap;


@Slf4j
public class InitGroovyScripts {

    private String rootPath;
    private Map<String, Object> caches = new ConcurrentHashMap<>();
    private GroovyScriptEngine groovyScriptEngine;
    private boolean inited = false;

    private List<Init> inits = new ArrayList<>();

    public InitGroovyScripts(String rootPath) {
        this.rootPath = rootPath;
    }

    public void init() {
        try {
            final File file = new File(rootPath);
            groovyScriptEngine = new GroovyScriptEngine(rootPath, InitGroovyScripts.class.getClassLoader());
            initScripts(file, groovyScriptEngine);
        } catch (Exception e) {
            log.info("init error =>", e);
        }
    }

    public void afterInit(ServletContext context) {
        inits.forEach(i -> i.init(context));
    }

    // 遍历文件夹中的所有文件？
    private void initScripts(File rootFile, GroovyScriptEngine engine) {
        String rootPath = rootFile.getAbsolutePath();
        int rootPathLength = rootPath.length();
        final Stack<File> files = new Stack<>();
        files.push(rootFile);
        while (!files.isEmpty()) {
            final File pop = files.pop();
            final File[] subFiles = pop.listFiles();
            if (subFiles != null) {
                for (File subFile: subFiles) {
                    if (subFile.isDirectory()) {
                        files.push(subFile);
                    } else {
                        final String absolutePath = subFile.getAbsolutePath();
                        // 剩余的部分
                        final String scriptName = absolutePath.substring(rootPathLength + 1);
                        final Object o = loadAScript(engine, scriptName);
                        if (o instanceof Init) {
                            inits.add((Init) o);
                        }
                    }
                }
            }
        }
    }

    private Object loadAScript(GroovyScriptEngine engine,  String scriptName) {
        log.info("script name is {}",  scriptName);
        try {
            final Class aClass = engine.loadScriptByName(scriptName);
            // 判断这个类是否继承自script
            log.info("script is {}", aClass);
            Object _script =  aClass.newInstance();
            caches.put(scriptName, _script);
            return _script;
        } catch (Exception e) {
            log.info("loadScript error =>", e);
            return null;
        }
    }

    public Object loadScript(String name) {
        final Object o = caches.computeIfAbsent(name, path -> loadAScript(groovyScriptEngine, path));
        return o;
    }

    public static void main(String[] args) {
        final InitGroovyScripts scripts = new InitGroovyScripts("web/groovy");
        scripts.init();
        final Script script = (Script) scripts.loadScript("hello.groovy");
        script.setProperty("aInt", 12);
        Object a = script.invokeMethod("test", null);
        System.out.println(a);
    }

}
